package main

import "fmt"

type Cat struct{
	Name string
	Age int
}

//write Data
func writeData(intChan chan int ){
	for i := 1; i <= 5000; i++{
		//放入数据
		intChan<- i
		fmt.Println("写入数据：",i)
	}
	close(intChan)
}

//read data
func readData(intChan chan int,exitChan chan bool){
	//for v := range intChan{
	//	fmt.Println("数据为",v)
	//}
	for{
		v,ok := <- intChan
		if !ok {
			break
		}
		fmt.Printf("读取数据 =%v\n",v)
	}
	exitChan<- true
}

func main(){
	//演示管道
	//1.创建一个可以存放3个int类型的管道
	var intChan chan int
	intChan = make(chan int,3 )
	//2.intChan是一个指针
	fmt.Printf("intChan的值=%v intChan本身的地址=%p\n",intChan,&intChan)

	//3.往管道写入数据
	intChan<- 10
	num := 211
	intChan<- num
	//4.管道的长度和cap(容量) ※※当给管道写入数据时，不能超过cap(容量) 否则会报错
	fmt.Printf("intChan的长度=%d,intChan的容量=%d\n",len(intChan),cap(intChan))

	//5.从管道取出数据
	var num2 int
	num = <-intChan
	fmt.Println("num2=",num2) //取出数据后，长度会减少

	//6.在没有使用协程的情况下，如果我们的管道数据全部取出，再取就会报告 deadlock
	num3 := <-intChan
	//num4 := <-intChan
	fmt.Println("num3=",num3/*,"num4=",num4*/)

	//案例
	allChan := make(chan interface{},3)//便捷声明
	cat := Cat{"小白猫",4}
	allChan <- cat
	newCat := <- allChan //拿出cat结构体 ※ 此时拿出来的内容不是结构体而是空接口，无法直接使用需要使用类型断言才可以拿出数据
	a := newCat.(Cat) //类型断言
	fmt.Printf("newCat.Name = %v",a.Name)

	//关闭管道 关闭后只能读，不可写
	close(allChan)
	intChan2 := make(chan int ,100)
	for i :=0 ; i < 100 ; i++{
		intChan2<- i * 2 //放入100个数据
	}
	close(intChan2)
	//遍历 管道最好使用for range 不然可能会异常
	for v := range intChan2{
		fmt.Println("v=",v)
	}

	//应用案例
	iChan1 := make(chan int ,50)
	exitChan := make(chan bool,1)
	go writeData(iChan1)
	go readData(iChan1,exitChan)
	for {
		v := <- exitChan
		if v {
			break
		}
	}

}
